/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.classdiagram.editpart;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.uml2.uml.DataType;
import org.eclipse.uml2.uml.Dependency;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.Generalization;

import com.cea.papyrus.core.PapyrusMessages;
import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.directedit.IDirectEdition;
import com.cea.papyrus.core.directedit.LabelDirectEditPolicy;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editor.mouseoveraction.ActionHandleManager;
import com.cea.papyrus.core.editpart.ContainerWithSemanticEditPart;
import com.cea.papyrus.core.figures.ClassifierFigure;
import com.cea.papyrus.core.figures.IconFigure;
import com.cea.papyrus.core.figures.NodeFigure;
import com.cea.papyrus.core.ui.dialogs.PapyrusMessageDialog;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Controller class for {@link DataType}.
 */
public class DataTypeEditPart extends ContainerWithSemanticEditPart {

	/**
	 * Creates a new DataTypeEditPart.
	 * @param modelManager manager in charge of models, graphic and domain
	 * @param graphNode parent of the graph node controlled by this edit part
	 */
	public DataTypeEditPart(GraphNode graphNode,ModelManager modelManager) {
		super(graphNode,modelManager);
	}

	/**
s	 * {@inheritDoc}
	 */
	@Override
	protected void createEditPolicies(){
		super.createEditPolicies();
		installEditPolicy( EditPolicy.DIRECT_EDIT_ROLE, new LabelDirectEditPolicy() );
		installEditPolicy(EditPolicy.LAYOUT_ROLE, new ClassElementLayoutEditPolicy(
				(XYLayout)getInvisibleContainer().getLayoutManager()));
		installActionHandle();
	}

	/**
	 * Install Action handles for this editPart.
	 * Use same toolEntries than those in palette
	 */
	protected void installActionHandle() {
		// Install mouse hover
		ActionHandleManager actionMngr = new ActionHandleManager(this);	
		// Create a toolbar of actions.
		PaletteDrawer entries = new PaletteDrawer("generalization tool");
		try {
			entries.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
					PapyrusMessages.AddGeneralizationCommand_Label, 
					PapyrusMessages.AddGeneralizationCommand_Description,
					Generalization.class,
					null));
		} catch (Exception e) {
			PapyrusMessageDialog.display(e.getMessage(), e);
		}
		actionMngr.addTool(entries, PositionConstants.NORTH, false, 5);

		// reset entries
		entries = new PaletteDrawer("dependency tool");
		try {
			entries.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
					PapyrusMessages.AddDependencyCommand_Label, 
					PapyrusMessages.AddDependencyCommand_Description,
					Dependency.class,
					null));
		} catch (Exception e) {
			PapyrusMessageDialog.display(e.getMessage(), e);
		}
		actionMngr.addTool(entries, PositionConstants.WEST, false, 5);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected IFigure createFigure() {
		// Force initialization of the manager when figure has changed
		manager = null;
		directEditionMode = IDirectEdition.UNDEFINED_DIRECT_EDITOR;
		// Try to get figure from ContainerWithSemanticEditPart
		IFigure fig = super.createFigure();
		if (fig != null) {
			return fig;
		}
		// else
		return new ClassifierFigure();		
	}

	/**
	 * Create the child <code>EditPart</code>
	 * for the given model object. This method is called from {@link #refreshChildren()}.
	 * <p>
	 * It adds the different container for Operation and Attribute lists, and other lists. 
	 * </p>
	 * @param model the Child model object
	 * @return The child EditPart
	 */
	@Override
	protected EditPart createChild(Object model) {
		if( model instanceof GraphNode)
		{
			EditPart part = null;
			//First graphNode=container of attributes
			if( ((GraphNode)model) == ((GraphNode)getGraphNode().getContained().get(0)) ) {
				part = new PropertyListEditPart((GraphNode)model,modelManager);
			} else if(((GraphNode)model) == ((GraphNode)getGraphNode().getContained().get(1))) {
				part = new OperationListEditPart((GraphNode)model, modelManager);
			} else {
				throw new RuntimeException("unknown model list");
			}
			part.setModel(model);
			return part;
		}
		return super.createChild(model);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public DataType getUmlElement(){
		Element e=((Uml1SemanticModelBridge)getGraphNode().getSemanticModel()).getElement();
		if(e instanceof ElementImport){//maybe this is an imported elment
			return (DataType)((ElementImport)e).getImportedElement();
		}
		return (DataType)e;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected void refreshVisuals() {
		Debug.debug(this, "refreshvisuals", channel);

		Dimension size = getGraphNode().getSize();
		Point p = getGraphNode().getPosition();
		Rectangle r = new Rectangle(p ,size);

		IFigure fig = getFigure();

		// if fig is a stereotype figure
		if (!(fig instanceof ClassifierFigure)) {
			IconFigure icf= (IconFigure)getFigure();
			icf.setName(getUmlElement().getName());

		} else {
			// Retrieve current class and figure
			org.eclipse.uml2.uml.DataType currentDataType = getUmlElement();
			com.cea.papyrus.umlutils.Element currentElement = new com.cea.papyrus.umlutils.Element(getUmlElement());

			ClassifierFigure f = (ClassifierFigure) fig; //get Class figure

			// if fig is a ClassFigure
			((NodeFigure) fig).refreshColors(getGraphNode());
			((NodeFigure) fig).refreshPresentation(getPresentation(), currentDataType, getGraphNode());
			boolean hasIcon  = currentElement.hasIcon();
			boolean hasShape = currentElement.hasShape();
			//f.refreshStereotypes(currentElement.getStereotypes(), getPresentation(), hasIcon, hasShape);
			f.refreshStereotypes(f.stereotypesLabel(this), getPresentation(), hasIcon, hasShape);

			f.setName(currentDataType.getName()); // set the name of the class

			//qualifiedName
			GraphNode gp= (GraphNode)getGraphNode().getContainer();
			f.refreshQualifiedName(gp,getGraphNode(), getUmlElement());

			//setAbstract
			f.setAbstract(currentDataType.isAbstract());//Is-it abstract?
		}
		((GraphicalEditPart) getParent()).setLayoutConstraint(this, fig, r);
	}

	/**
	 * Returns the Name Label of this edit part.
	 * @return Label the label figure from the graphical representation
	 */
	protected Label getNameLabel() {
		IFigure fig = getFigure();
		if (fig instanceof IconFigure) {
			return (Label) fig;
		} else if (fig instanceof ClassifierFigure) {
			return ((ClassifierFigure) fig).getNameLabel();
		} else {
			Debug.error(this, "DataTypeEditPart::getNameLabel() : Unknown Figure type.", channel);
			return null;
		}
	}

	/**
	 * Returns the invisible container from the Classifier Figure if the current representation of the Class is a {@link ClassifierFigure}.
	 * @return the invisible container from the Classifier Figure or the shape figure if representation is a custom representation
	 */
	public IFigure getInvisibleContainer() {
		if (getFigure() instanceof ClassifierFigure) {
			return ((ClassifierFigure) getFigure()).getInvibleContainer();
		} else {
			// Figure is a shape
			return getFigure();
		}
	}

	/**
	 * Returns the content pane from the Classifier Figure if the current representation of the Class is a {@link ClassifierFigure}.
	 * @return the content pane from the Classifier Figure or the shape figure if representation is a custom representation
	 */
	@Override
	public IFigure getContentPane() {
		if (getFigure() instanceof ClassifierFigure) {
			return ((ClassifierFigure) getFigure()).getContentPane();
		} else {
			// Figure is a shape
			return getFigure();
		}
	}
}
